// 单例模式是创建型设计模式的一种。确保全局中有且仅有一个对象实例，并提供一个访问它的全局访问点
// 1.常规方案
const Singleton = (function () {
    let instance

    function init () {
        // 私有变量和方法
        let privateVariable = 'Im also private'
        let privateRandomNumber = Math.random()

        function privateMethod () {
            console.log('I am private')
        }

        return {
            // 公共变量和方法
            publicProperty: 'I am also public',
            getRandomNumber: function () {
                return privateRandomNumber
            },
            publicMethod: function () {
                console.log('The public can see me!')
            },
        }
    }

    return {
        getInstance: function () {
            if (!instance) {
                instance = init()
            }
            return instance
        },
    }
})()
// Usage:
let singleA = Singleton.getInstance()
let singleB = Singleton.getInstance()
console.log(singleA.getRandomNumber() === singleB.getRandomNumber()) // true

// 2.Proxy属性拦截实现
/**
 *
 * @param {Class} className
 * @type {Function} ProxySingleton
 * @constructor
 */
const ProxySingleton = (className) => {
    return new Proxy(className.prototype.constructor, {
        instance: null,
        construct: (target, argArray) => {
            if (!this.instance) {
                this.instance = new target(...argArray)
            }
            return this.instance
        },
    })
}

class TestClass {
    constructor (msg) {
        this.msg = msg
    }

    printMsg () {
        console.log(this.msg)
    }
}

let TestClassSingleton = ProxySingleton(TestClass)
let obj1 = new TestClassSingleton('1')
obj1.printMsg() // 1
let obj2 = new TestClassSingleton('2')
obj2.printMsg() // 1
